package com.geor.gcv.ict.train;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;

import com.geor.gcv.core.mat.Mats;

/**
 * 自定义ML模块的实现
 * 
 * @author lusongnan
 *
 */
public class SimpleMl implements Ml {

	Map<String, List<Mat>> matMaps = new HashMap<String, List<Mat>>();

	@Override
	public void load(String path) {
		if (!new File(path).isDirectory()) {
			throw new RuntimeException(String.format("[%s]该类目前只能加载目录", SimpleMl.class.getSimpleName()));
		}

		File files[] = new File(path).listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				String name = file.getName();
				File temps[] = file.listFiles();
				List<Mat> lists = new ArrayList<Mat>();
				for (File file2 : temps) {
					lists.add(Highgui.imread(file2.getAbsolutePath()));
				}
				matMaps.put(name, lists);
			}
		}

	}

	@Override
	public void train(Mat trainData, Mat label, String out) {
		throw new UnsupportedOperationException("不支持该操作!");
	}

	@Override
	public float predict(Mat sample) {
		float result = calculate(sample);

		return result;
	}

	private int calculate(Mat sample) {
		Map<String, Float> maps = new HashMap<String, Float>();

		for (String name : matMaps.keySet()) {
			for (Mat mat : matMaps.get(name)) {
				float result = cal(mat, sample);

				if (result < 0.6) {
					continue;
				}

				if (maps.get(name) != null) {
					maps.put(name, Math.max(maps.get(name), result));
				} else {
					maps.put(name, result);
				}
			}
		}

		List<Float> lists = new ArrayList<Float>();
		for (Object obj : maps.keySet()) {
			lists.add(maps.get(obj));
		}
		if (lists.size() != 0) {
			float max = lists.get(0);
			for (int i = 1; i < lists.size(); i++) {
				float cur = lists.get(i);
				if (max < cur) {
					max = cur;
				}
			}

			for (String str : maps.keySet()) {
				if (max == maps.get(str)) {
					return Integer.parseInt(str);
				}
			}
		}

		return 0;

	}

	private float cal(Mat img1, Mat img2) {
		float img1_temps[] = Mats.genSimpleMatArray(img1);
		float img2_temps[] = Mats.genSimpleMatArray(img2);
		// dot( a1,a2 )/( sqrt( sum( a1.*a1 ) ) * sqrt( sum( a2.*a2 ) ) )
		float dot = 0;
		for (int i = 0; i < img1.rows() * img1.cols(); i++) {
			dot += img1_temps[i] * img2_temps[i];
		}

		float a1 = 0;
		for (float d : img1_temps) {
			a1 += d * d;
		}

		a1 = (float) Math.sqrt(a1);

		float a2 = 0;
		for (float d : img2_temps) {
			a2 += d * d;
		}
		a2 = (float) Math.sqrt(a2);

		float result = dot / (a1 * a2);

		return result;
	}

	@Override
	public boolean isSuccess() {
		// TODO Auto-generated method stub
		return false;
	}
}
